/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ar.com.wholeconsulting.pacc.gui.utils.table;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

/**
 *
 * @author pable
 */
public class AbstractEditorTableModel extends DefaultTableModel {

    private Class[] types = new Class[]{
        java.lang.String.class, java.lang.Object.class
    };
    private boolean[] canEdit = new boolean[]{
        false, true
    };
    private static String GET = "get";
    private static String SET = "set";
    private String[] fieldNames;
    private Object instance;

    public AbstractEditorTableModel(Object[][] nombreAtributos, JTable table, TableCellEditor editors[], String[] fieldNames, Object instance) {
        super(nombreAtributos, new String[]{"Atributo", "Valor"});
        table.setModel(this);
        EachRowTableEditor editor = new EachRowTableEditor(table);
        for (int i = 0; i < editors.length; i++) {
            editor.setEditorAt(i, editors[i]);
        }
        this.instance = instance;
        this.fieldNames = fieldNames;
        table.getColumn("Valor").setCellEditor(editor);
    }

    @Override
    public Object getValueAt(int row, int column) {
        if (column != 0) {
            try {
                String method = GET + fieldNames[row];
                Method mt = getMethod(method);
                return mt.invoke(instance);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalArgumentException ex) {
                Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvocationTargetException ex) {
                Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
            }
            return null;
        } else {
            return super.getValueAt(row, column);
        }
    }

    @Override
    public void setValueAt(Object aValue, int row, int column) {
        if (column != 0) {
            try {
                String method = SET + fieldNames[row];
                Method mt = getMethod(method);
                mt.invoke(instance, convertParameter(mt.getParameterTypes()[0], aValue));
            } catch (IllegalAccessException ex) {
                Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalArgumentException ex) {
                Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvocationTargetException ex) {
                Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public Class getColumnClass(int columnIndex) {
        return types[columnIndex];
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return canEdit[columnIndex];
    }

    private Method getMethod(String method) {
        for (Method mt : instance.getClass().getMethods()) {
            if (mt.getName().equalsIgnoreCase(method)) {
                return mt;
            }
        }
        throw new IllegalArgumentException();
    }

    private Object convertParameter(Class clazz, Object value) {
        if (clazz.getName().equals(value.getClass().getName())) {
            return value;
        } else if (!clazz.getName().equals(java.lang.String.class.getName())
                && value.getClass().getName().equals(java.lang.String.class.getName())) {
            try {
                Method method = clazz.getMethod("valueOf", java.lang.String.class);
                if (Modifier.isStatic(method.getModifiers())) {
                    try {
                        return method.invoke(null, value);
                    } catch (IllegalAccessException ex) {
                        Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (IllegalArgumentException ex) {
                        Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (InvocationTargetException ex) {
                        Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            } catch (NoSuchMethodException ex) {
                Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                Logger.getLogger(AbstractEditorTableModel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        throw new IllegalArgumentException();
    }
}
